using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;
using System.IO;

using System.Data;

using Pampa.Grid.Utils;

using Pampa.Grid.Core;
using Pampa.Grid.Data;
using Pampa.Grid.UI.Exceptions;
using Pampa.Grid.Exceptions;
using Pampa.Grid.Core.Filters;

using Pampa.WebControls;

namespace Pampa.Grid.UI.CustomControls
{
    [DesignerAttribute(typeof(BaseDesigner), typeof(System.ComponentModel.Design.IDesigner))]
    public class ColumnManager : BaseControl
    {
        private string gridID;
        private string contextMenuCssClass;
        private string pathImages;
        private CustomGrid customGrid;

        public ColumnManager()
        {
            this.CssClass = "columnManagerDefault";
            this.ContextMenuCssClass = "contextMenuDefault";
            this.PathImages = "Pampa.Grid" + GetImagesPath();
        }

        #region Properties

        public string GridID
        {
            get { return gridID; }
            set { gridID = value; }
        }

        public string ContextMenuCssClass
        {
            get { return contextMenuCssClass; }
            set { contextMenuCssClass = value; }
        }

        public string PathImages
        {
            get { return pathImages; }
            set { pathImages = value; }
        }

        public CustomGrid Grid
        {
            get
            {
                if (customGrid == null && this.Page != null)
                {
                    customGrid = (CustomGrid)Page.FindControl(this.GridID);
                }

                if (customGrid == null)
                {
                    throw (new CustomGridException("QuickFiltersPanel Error. There is no CustomGrid associated to the panel.'"));
                }

                return customGrid;
            }
            set
            {
                customGrid = value;
                this.GridID = customGrid.ID;
            }
        }

        #endregion

        #region Load

        protected override void OnLoad(EventArgs e)
        {
            if (this.CssClass == "columnManagerDefault")
                RegisterStyleSheet("Pampa.Grid/ColumnManager.css");

            if (this.ContextMenuCssClass == "contextMenuDefault")
                RegisterStyleSheet("Pampa.Grid/ContextMenu.css");

            RegisterLibrary("Pampa.Common/Common.js");
            RegisterLibrary("Pampa.Common/TextButton.js");

            RegisterLibrary("Pampa.Grid/DragDrop.js");
            RegisterLibrary("Pampa.Grid/ContextMenu.js");
            RegisterLibrary("Pampa.Grid/ColumnManager.js");

            base.OnLoad(e);
        }

        #endregion

        #region Render

        protected override void RenderContents(HtmlTextWriter output)
        {
            if (this.Grid == null)
            {
                output.WriteLine("There is no grid called " + this.GridID);
            }
            else if (!this.Grid.Configuration.Configurable)
            {
                output.WriteLine(this.Grid.Configuration.NoConfigurableMessage);
            }
            else
            {
                // Containers
                output.AddStyleAttribute("height", "90%");

                output.AddAttribute("cellspacing", "0");
                output.AddAttribute("cellpadding", "0");
                output.RenderBeginTag(HtmlTextWriterTag.Table);
                output.RenderBeginTag(HtmlTextWriterTag.Tr);

                output.AddStyleAttribute("vertical-align", "top");
                output.RenderBeginTag(HtmlTextWriterTag.Td);
                RenderAllContainer(output);
                output.RenderEndTag();

                output.AddStyleAttribute("vertical-align", "top");
                output.RenderBeginTag(HtmlTextWriterTag.Td);
                RenderVisiblesContainer(output);
                output.RenderEndTag();

                output.AddStyleAttribute("vertical-align", "top");
                output.RenderBeginTag(HtmlTextWriterTag.Td);
                RenderOrdersContainer(output);
                output.RenderEndTag();

                output.AddStyleAttribute("vertical-align", "bottom");
                output.RenderBeginTag(HtmlTextWriterTag.Td);
                RenderTrash(output);
                output.RenderEndTag();

                output.RenderEndTag();
                output.RenderEndTag();

                // Construyo el objeto cliente
                output.WriteLine("<script type=\"text/javascript\">");
                output.WriteLine("var obj" + this.ID + " = new ColumnManager('" + this.ID + "', '" + this.GridID + "');");

                output.WriteLine("obj" + this.ID + ".cssClass = '" + this.CssClass + "';");

                foreach(ColumnConfig columnConfig in this.Grid.Configuration.Columns)
                {
                    string title = this.Grid.GetColumn(columnConfig.Field).Title;
                    output.WriteLine("obj" + this.ID + ".titles['" + columnConfig.Field + "'] = '" + title + "';");
                }

                output.WriteLine("obj" + this.ID + ".setContainers('" + this.ID + "_All', '" + this.ID + "_Visibles', '" + this.ID + "_Orders', '" + this.ID + "_Trash');");
                output.WriteLine("obj" + this.ID + ".buildContextMenus('" + this.ContextMenuCssClass + "');");

                output.WriteLine("</script>");
            }
        }

        private void RenderTrash(HtmlTextWriter output)
        { 
            output.AddAttribute("id", this.ID + "_Trash");
            output.AddAttribute("class", "trash");
            output.AddAttribute("nickName", "trash");
            output.RenderBeginTag(HtmlTextWriterTag.Div);

            output.AddAttribute("src", GetResourceUrl(this.PathImages) + "/trash.gif");
            output.RenderBeginTag(HtmlTextWriterTag.Img);
            output.RenderEndTag();            

            output.RenderEndTag();

            output.WriteLine("<script>");
            output.WriteLine("trashPathImages = '" + GetResourceUrl(this.PathImages) + "';");
            output.WriteLine("</script>");
        }
        
        private void RenderAllContainer(HtmlTextWriter output)
        {
            output.RenderBeginTag(HtmlTextWriterTag.Table);

            // Title
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.AddAttribute("class", "title");
            output.RenderBeginTag(HtmlTextWriterTag.Td);
            output.Write(Resources.ConfigManager.AllColumns);
            output.RenderEndTag();
            output.RenderEndTag();

            // Container
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.RenderBeginTag(HtmlTextWriterTag.Td);

            output.AddAttribute("id", this.ID + "_All");
            output.AddAttribute("class", "dragContainer");
            output.AddAttribute("nickName", "All");

            output.RenderBeginTag(HtmlTextWriterTag.Div);

            // Ojo. De esta forma las columnas se muestran ordenadas por su id ('field')
            foreach (Column column in this.Grid.Columns)
            {
                if (column.IsElegible)
                {
                    RenderBox(column.Field, column.Title, "All", output);
                }
            }

            output.RenderEndTag();
            output.RenderEndTag();
            output.RenderEndTag();

            output.RenderEndTag();        
        }

        private void RenderVisiblesContainer(HtmlTextWriter output)
        {
            output.RenderBeginTag(HtmlTextWriterTag.Table);

            // Title
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.AddAttribute("class", "title");
            output.RenderBeginTag(HtmlTextWriterTag.Td);
            output.Write(Resources.ConfigManager.VisibleColumns);
            output.RenderEndTag();
            output.RenderEndTag();

            // Container
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.RenderBeginTag(HtmlTextWriterTag.Td);

            output.AddAttribute("id", this.ID + "_Visibles");
            output.AddAttribute("class", "dragContainer");
            output.AddAttribute("nickName", "Visibles");

            output.RenderBeginTag(HtmlTextWriterTag.Div);

            Column column;
            foreach (string visibleColumn in this.Grid.Configuration.VisibleColumns)
            {
                column = this.Grid.GetColumn(visibleColumn);
                RenderVisiblesBox(visibleColumn, column.Title, output);
            }

            output.RenderEndTag();
            output.RenderEndTag();
            output.RenderEndTag();

            output.RenderEndTag();    
        }

        private void RenderOrdersContainer(HtmlTextWriter output)
        {
            output.RenderBeginTag(HtmlTextWriterTag.Table);

            // Title
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.AddAttribute("class", "title");
            output.RenderBeginTag(HtmlTextWriterTag.Td);
            output.Write(Resources.ConfigManager.OrderByColumns);
            output.RenderEndTag();
            output.RenderEndTag();

            // Container
            output.RenderBeginTag(HtmlTextWriterTag.Tr);
            output.RenderBeginTag(HtmlTextWriterTag.Td);

            output.AddAttribute("id", this.ID + "_Orders");
            output.AddAttribute("class", "dragContainer");
            output.AddAttribute("nickName", "Orders");

            output.RenderBeginTag(HtmlTextWriterTag.Div);

            Column column;
            foreach (KeyValuePair<string, OrderDirection> order in this.Grid.Configuration.OrderBy)
            {
                column = this.Grid.GetColumn(order.Key);
                RenderOrderBox(order.Key, column.Title, order.Value, output);
            }

            output.RenderEndTag();
            output.RenderEndTag();
            output.RenderEndTag();

            output.RenderEndTag();   
        }

        private void RenderBox(string id, string title, string parent, HtmlTextWriter output)
        {
            RenderBoxCommonAttributes(id, title, parent, output);

            output.RenderBeginTag(HtmlTextWriterTag.Div);
            output.WriteLine(title);
            output.RenderEndTag();   
        }

        private void RenderVisiblesBox(string id, string title, HtmlTextWriter output)
        {
            RenderBoxCommonAttributes(id, title, "Visibles", output);

            output.RenderBeginTag(HtmlTextWriterTag.Div);
            output.WriteLine(title);
            output.RenderEndTag();
        }

        private void RenderOrderBox(string id, string title, OrderDirection direction, HtmlTextWriter output)
        {
            string strDirection = Enum.GetName(typeof(OrderDirection), direction);
            string strAbDirection = GetAbDirection(direction);
            string desc = title + " (" + strAbDirection + ")";

            RenderBoxCommonAttributes(id, title, "Orders", output);
            output.AddAttribute("direction", strDirection);
            output.AddAttribute("onclick", "ColumnManager_swapDirection(this, event)");
            output.AddAttribute("onmouseup", "ColumnManager_contextualMenu(this, event)");

            output.RenderBeginTag(HtmlTextWriterTag.Div);
            output.WriteLine(desc);
            output.RenderEndTag();
        }

        private void RenderBoxCommonAttributes(string id, string title, string parent, HtmlTextWriter output)
        {
            output.AddAttribute("id", id);
            output.AddAttribute("title", title);
            output.AddAttribute("parent", parent);
            output.AddAttribute("idManager", this.ID);
            output.AddAttribute("class", "dragBox");
            output.AddAttribute("overClass", "overDragBox");
            output.AddAttribute("dragClass", this.CssClass + "_dragingBox ");
            output.AddAttribute("afterMoveFunction", "ColumnManager_afterMove");
        }

        #endregion

        #region Private Functions

        private string GetAbDirection(OrderDirection direction)
        {
            switch (direction)
            {
                case OrderDirection.Descending:
                    return "Desc";
                case OrderDirection.Ascending:
                    return "Asc";
                default:
                    return "";
            }
        }

        #endregion
    }

}